#include "config.h"

#include <clx/libECM.h>

#include "ms2sim.h"

static FILE	*logfp;
static char	*logpath;
static ECMBOOL	is_stdout = ECM_FALSE;

static const char *
get_current_datetimestr(void)
{
	ecm_datetime_t	datetime;
	static char	buf[1024];

	ecm_get_current_datetime(&datetime);
	ecm_snprintf(buf, 1024, "%04u-%02u-%02u %02u:%02u:%02u",
		     datetime.year, datetime.mon, datetime.mday,
		     datetime.hour, datetime.min, datetime.sec);

	return buf;
}

void
vprintlog(const char *fmt, va_list ap)
{
	char	*buf;

	if (logfp == NULL)
		return;

        ecm_vasprintf(&buf, fmt, ap);
        ecm_fprintf(logfp, "%s", buf);
        ecm_free(buf);
}

void
printlog(const char *fmt, ...)
{
        va_list ap;

	if (logfp == NULL)
		return;

        va_start(ap, fmt);
	vprintlog(fmt, ap);
        va_end(ap);
}

static void
report_configuration(void)
{
	printlog("# Simulation Configuration:\n");

	printlog("Real Duration:         %s\n", msl_get_duration_str(ts_subsys / 1000000));
	printlog("Duration:              %s\n", msl_get_duration_str(duration));
	printlog("Stat Duration:         %s\n", msl_get_duration_str(stat_duration));
	printlog("Arrival Rate:          %lf/min\n", arrival_rate * 60);
	printlog("Skew:                  %lf\n", skew);
	printlog("Disk Block Size:       %s\n", msl_get_capacity_str((ecm_double)disk_blksize));
	printlog("Disk Bandwidth:        %s\n", msl_get_bandwidth_str((ecm_double)disk_BW));
	printlog("Block Cache Policy:    %s\n", bcache_mgmt_name);
	printlog("Block Cache Size:      %s\n", msl_get_capacity_str((ecm_double)cache_blksize));
	printlog("Block Cache Pool Size: %s\n", msl_get_capacity_str((ecm_double)((ecm_uint64)cache_blksize * n_caches)));
	printlog("Disk Bandwidth:        %s\n", msl_get_bandwidth_str((ecm_double)disk_BW));
	printlog("Disksim param:         %s\n", ecm_safe_str(disksim_param));
	printlog("Session Length Dist.:  %s\n", msl_sesslen_get_typestr(sesslen_type)); 
	printlog("Inter-Seek Dist.:      %s\n", msl_istime_get_typestr(istime_type)); 
	printlog("\n");

	printlog("# Module Configuration:\n");
	if (bcache_op->show_conf != NULL)
		bcache_op->show_conf();
	printlog("\n");
}

static void
report_result(void)
{
	printlog("# Simuation Result:\n");

	report_session_result();
	report_request_result();
	report_bcache_result();
	report_disk_result();
	report_network_result();
	report_media_result();
}

FILE *
open_logfile(const char *basepath, char **plogpath)
{
	char	*logpath;
	FILE	*fp;

	ecm_datetime_t	datetime;

	ecm_get_current_datetime(&datetime);

	ecm_asprintf(&logpath, "%s_%02u%02u_%02u%02u%02u.log",
		     basepath,
		     datetime.mon, datetime.mday,
		     datetime.hour, datetime.min, datetime.sec);
	fp = ecm_fopen(logpath, "a+");
	if (fp != NULL && plogpath)
		*plogpath = logpath;
	else
		ecm_free(logpath);
	return fp;
}

ECMBOOL
setup_logging(void)
{
	if (ecm_strcmp(logbasepath, "-") == 0) {
		is_stdout = ECM_TRUE;
		logfp = ecm_stdout;
	}
	else {
		logfp = open_logfile(logbasepath, &logpath);
		if (logfp == NULL)
			return ECM_FALSE;
	}

	printlog("# Simulation start at %s\n\n", get_current_datetimestr());

	return ECM_TRUE;
}

void
cleanup_logging(void)
{
	report_configuration();
	report_result();

	printlog("\n");
	printlog("# Simulation ended at %s\n", get_current_datetimestr());

	if (logfp && !is_stdout) {
		ecm_fclose(logfp);
		if (allowed_loss_ratio_violated)
			ecm_unlink(logpath);
	}
}
